library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;

entity mymipspipe is
	generic
	(
		DATA_WIDTH	: natural  :=	32;
		REG_WIDTH	: natural  :=	5;
		ALUC_WIDTH	: natural  :=	5
	);


	port
	(
		-- Input ports
		clock : in std_logic;
		ram_clock : in std_logic;
		rom_clock : in std_logic;
		resetn : in std_logic;
		-- IRQ
		irq0 : in std_logic;
		irq1 : in std_logic;
		irq2 : in std_logic;
		irq3 : in std_logic;
		
		-- Output ports
		pc_out	: out std_logic_vector(DATA_WIDTH-1 downto 0);
--		ins_out	: out std_logic_vector(DATA_WIDTH-1 downto 0);
		inst_out : out std_logic_vector(DATA_WIDTH-1 downto 0);
		fwda_out : out std_logic_vector(1 downto 0);
		fwdb_out : out std_logic_vector(1 downto 0);
		da_out : out std_logic_vector(DATA_WIDTH-1 downto 0);
		db_out : out std_logic_vector(DATA_WIDTH-1 downto 0);		
		dimm_out : out std_logic_vector(DATA_WIDTH-1 downto 0);

--		aluc_out	: out std_logic_vector(ALUC_WIDTH-1 downto 0);
--		wrfnd_out	: out std_logic_vector(REG_WIDTH-1 downto 0);
--		wrfdi_out	: out std_logic_vector(DATA_WIDTH-1 downto 0);
		ealu_out	: out std_logic_vector(DATA_WIDTH-1 downto 0);
--		malu_out	: out std_logic_vector(DATA_WIDTH-1 downto 0);
--		walu_out : out std_logic_vector(DATA_WIDTH-1 downto 0);
		mb_out	: out std_logic_vector(DATA_WIDTH-1 downto 0);
		cen_out : out std_logic;
		dcacheok_out : out std_logic;
		irq_out : out std_logic;
		rtn_out	: out std_logic;
		iret_out	: out std_logic;
		irqmask_out : out std_logic;
		irqaddr_out	: out std_logic_vector(DATA_WIDTH-1 downto 0);
		mmo_out : out std_logic_vector(DATA_WIDTH-1 downto 0)
--		wmo_out : out std_logic_vector(DATA_WIDTH-1 downto 0)
	);
end mymipspipe;

architecture struct of mymipspipe is
component pipepc
	port
	(
		-- Input ports
		clk	: in  std_logic;
		clrn : in std_logic;
		cen : in std_logic;
		wpc	: in std_logic;
		npc : in std_logic_vector(DATA_WIDTH-1 downto 0);
		irqmaskpc : in std_logic;
		-- Output ports
		irqmaskf : out std_logic;
		pc : out std_logic_vector(DATA_WIDTH-1 downto 0)		
	);
end component;

component pipeif
	port
	(
		-- Input ports
		branch	: in  std_logic;
		pc : in std_logic_vector(DATA_WIDTH-1 downto 0);
		bpc : in std_logic_vector(DATA_WIDTH-1 downto 0);
		rom_clock : std_logic;
		-- Output ports
		npc : out std_logic_vector(DATA_WIDTH-1 downto 0);
		pc4 : out std_logic_vector(DATA_WIDTH-1 downto 0);
		ins : out std_logic_vector(DATA_WIDTH-1 downto 0)
	);
end component;

component pipeir
	port
	(
		-- Input ports
		pc4 : in std_logic_vector(DATA_WIDTH-1 downto 0);
		ins : in std_logic_vector(DATA_WIDTH-1 downto 0);
		wir : in std_logic;
		clk : in std_logic;
		clrn : in std_logic;
		cen : in std_logic;		
		irq : in std_logic;		
		-- Output ports
		irqmask : out std_logic;
		pcf : out std_logic_vector(DATA_WIDTH-1 downto 0);
		inst : out std_logic_vector(DATA_WIDTH-1 downto 0)
	);
end component;

component pipeid
	port
	(
		-- Input ports
		-- to control unit
		mwreg : in std_logic;
		mm2reg : in std_logic;
		mwmem : in std_logic;
		mdesr : in std_logic_vector(REG_WIDTH-1 downto 0);
		ewreg : in std_logic;
		em2reg : in std_logic;
		edesr : in std_logic_vector(REG_WIDTH-1 downto 0);
		-- from pipeir
		pcf : in std_logic_vector(DATA_WIDTH-1 downto 0);
		inst : in std_logic_vector(DATA_WIDTH-1 downto 0);
		irqmask : in std_logic;
		-- from pipewreg
		wrfnd : in std_logic_vector(REG_WIDTH-1 downto 0);
		-- from pipewb
		wrfdi : in std_logic_vector(DATA_WIDTH-1 downto 0);
		-- from pipeexe
		ealu : in std_logic_vector(DATA_WIDTH-1 downto 0);
		-- from pipemreg
		malu : in std_logic_vector(DATA_WIDTH-1 downto 0);
		-- from pipemem
		mmo : in std_logic_vector(DATA_WIDTH-1 downto 0);
		dcacheok : in std_logic;
		-- from pipemwreg
		wwreg : in std_logic;
		-- from outside
		clk : in std_logic;
		clrn : in std_logic;
		
		-- Output ports
		-- to pipeif
		fwda_out : out std_logic_vector(1 downto 0);
		fwdb_out : out std_logic_vector(1 downto 0);
		bpc : out std_logic_vector(DATA_WIDTH-1 downto 0);
		branch : out std_logic;
		jpatch : out std_logic;
		iret : out std_logic;
		-- wpcir
		nostall : out std_logic;
		cen : out std_logic;
		-- to pipedereg
		wreg : out std_logic;
		m2reg : out std_logic;
		wmem : out std_logic;
		aluc : out std_logic_vector(ALUC_WIDTH-1 downto 0);
		aluimm : out std_logic;
		a : out std_logic_vector(DATA_WIDTH-1 downto 0);
		b : out std_logic_vector(DATA_WIDTH-1 downto 0);
		imm : out std_logic_vector(DATA_WIDTH-1 downto 0);
		desr : out std_logic_vector(REG_WIDTH-1 downto 0);
		shift : out std_logic		
	);
end component;

component pipedereg
	port
	(
		-- Input ports
		-- from pipeid
		dwreg : in std_logic;
		dm2reg : in std_logic;
		dwmem : in std_logic;
		daluc : in std_logic_vector(ALUC_WIDTH-1 downto 0);
		daluimm : in std_logic;
		da : in std_logic_vector(DATA_WIDTH-1 downto 0);
		db : in std_logic_vector(DATA_WIDTH-1 downto 0);
		dimm : in std_logic_vector(DATA_WIDTH-1 downto 0);
		ddesr : in std_logic_vector(REG_WIDTH-1 downto 0);
		dshift : in std_logic;
		-- from outside
		cen : in std_logic;
		clk : in std_logic;
		clrn : in std_logic;
		
		-- Output ports	
		ewreg : out std_logic; -- to pipeemreg and pipeid
		em2reg : out std_logic; -- to pipeemreg and pipeid
		ewmem : out std_logic; -- to pipeemreg		
		-- to pipeexe
		ealuc : out std_logic_vector(ALUC_WIDTH-1 downto 0);
		ealuimm : out std_logic;
		ea : out std_logic_vector(DATA_WIDTH-1 downto 0);
		eb : out std_logic_vector(DATA_WIDTH-1 downto 0);
		eimm : out std_logic_vector(DATA_WIDTH-1 downto 0);
		eshift : out std_logic;
		-- to pipeid and pipeemreg
		edesr : out std_logic_vector(REG_WIDTH-1 downto 0)
	);
end component;

component pipeexe
	port
	(
		-- Input ports
		-- from pipedereg
		ealuc : in std_logic_vector(ALUC_WIDTH-1 downto 0);
		ealuimm : in std_logic;
		ea : in std_logic_vector(DATA_WIDTH-1 downto 0);
		eb : in std_logic_vector(DATA_WIDTH-1 downto 0);
		eimm : in std_logic_vector(DATA_WIDTH-1 downto 0);
		eshift : in std_logic;
		-- Output ports
		ealu :out std_logic_vector(DATA_WIDTH-1 downto 0)
	);
end component;

component pipeemreg
	port
	(
		-- Input ports
		-- from pipedereg
		ewreg : in std_logic;
		em2reg : in std_logic;
		ewmem : in std_logic;
		eb : in std_logic_vector(DATA_WIDTH-1 downto 0);
		edesr : in std_logic_vector(REG_WIDTH-1 downto 0);
		-- from pipeexe
		ealu : in std_logic_vector(DATA_WIDTH-1 downto 0);
		-- from outside
		cen : in std_logic;
		clk : in std_logic;
		clrn : in std_logic;
		-- Output ports
		-- to pipeid and pipemwreg
		mwreg : out std_logic;
		mm2reg : out std_logic;
		-- to pipemem
		mwmem : out std_logic;
		malu : out std_logic_vector(DATA_WIDTH-1 downto 0);
		mb : out std_logic_vector(DATA_WIDTH-1 downto 0);
		mdesr : out std_logic_vector(REG_WIDTH-1 downto 0)
	);
end component;

component pipemem
	port
	(
		re : in std_logic;
		we : in std_logic;
		a : in std_logic_vector(DATA_WIDTH-1 downto 0);
		di : in std_logic_vector(DATA_WIDTH-1 downto 0);
		clk : in std_logic; -- CPU Clock
		memclk : in std_logic; -- Memory Clock
		-- Output ports
		dcacheok : out std_logic;
		-- mmo
		dataout : out std_logic_vector(DATA_WIDTH-1 downto 0)
	);
end component;

component pipemwreg
	port
	(
		-- Input ports
		-- from pipeemreg
		mwreg : in std_logic;
		mm2reg : in std_logic;
		malu : in std_logic_vector(DATA_WIDTH-1 downto 0);
		mdesr : in std_logic_vector(REG_WIDTH-1 downto 0);
		-- from pipemem
		mmo : in std_logic_vector(DATA_WIDTH-1 downto 0);
		-- from outside
		cen : in std_logic;
		clk : in std_logic;
		clrn : in std_logic;
		-- Output ports
		-- to pipeid
		wwreg : out std_logic;
		-- to pipewb
		wm2reg : out std_logic;
		wmo : out std_logic_vector(DATA_WIDTH-1 downto 0);
		walu : out std_logic_vector(DATA_WIDTH-1 downto 0);
		-- to pipeid wrfnd
		wdesr : out std_logic_vector(REG_WIDTH-1 downto 0)
	);
end component;

component irqcu
	port
	(
		-- Input ports
		irq_0	: in std_logic;
		irq_1	: in std_logic;
		irq_2	: in std_logic;
		irq_3	: in std_logic;
		clock	: in std_logic;
		iret	: in std_logic;
		jpatch	: in std_logic;
		--irqmask : in std_logic;
		pc	: in std_logic_vector(DATA_WIDTH-1 downto 0);
		
		-- Output ports
		irqaddr	: out std_logic_vector(DATA_WIDTH-1 downto 0);
		irq	: out std_logic;
		rtn	: out std_logic
	);	
end component;

component lpm_mux32
	PORT
	(
		data0x		: IN STD_LOGIC_VECTOR (31 DOWNTO 0);
		data1x		: IN STD_LOGIC_VECTOR (31 DOWNTO 0);
		sel		: IN STD_LOGIC ;
		result		: OUT STD_LOGIC_VECTOR (31 DOWNTO 0)
	);
end component;

signal bpc,npc,pc,pc4,ins,pcf,inst,irqaddr,npc_irq: std_logic_vector(DATA_WIDTH-1 downto 0);
signal wrfdi,ealu,malu,walu,mb,mmo,wmo: std_logic_vector(DATA_WIDTH-1 downto 0);
signal da,db,dimm: std_logic_vector(DATA_WIDTH-1 downto 0);
signal ea,eb,eimm: std_logic_vector(DATA_WIDTH-1 downto 0);
signal wrfnd,mdesr,edesr,ddesr,daluc,ealuc: std_logic_vector(REG_WIDTH-1 downto 0);
signal wpcir,branch,dcacheok,cen,iret,irq,rtn,irqmaskf,irqmask,jpatch: std_logic;
signal dwreg,dm2reg,dwmem,daluimm,dshift : std_logic;
signal ewreg,em2reg,ewmem,ealuimm,eshift : std_logic;
signal mwreg,mm2reg,mwmem : std_logic;
signal wwreg,wm2reg : std_logic;

begin
	regpc: pipepc port map(
		clk => clock,
		clrn => resetn,
		cen => cen,
		wpc => wpcir,
		npc => npc_irq,
		irqmaskpc => irq0 or irq1 or irq2 or irq3,
		irqmaskf => irqmaskf,
		pc => pc
	);
	pc_out <= pc;
	ifetch: pipeif port map(
		branch => branch,
		pc => pc,
		bpc => bpc,
		rom_clock => rom_clock,
		npc => npc,
		pc4 => pc4,
		ins => ins
	);
	irqcontrolunit: irqcu port map(
		-- Input ports
		irq_0 => irq0,
		irq_1 => irq1,
		irq_2 => irq2,
		irq_3 => irq3,
		clock => rom_clock,
		iret => iret,
		pc => npc,
		jpatch => jpatch,		
		-- Output ports
		irqaddr	=> irqaddr,
		irq	=> irq,
		rtn => rtn
	);
	iret_out <= iret;
	irq_out <= irq;
	rtn_out <= rtn;
	irqaddr_out <= irqaddr;
	irqmux: lpm_mux32 port map(
		data0x => npc,
		data1x => irqaddr,
		sel => irq or rtn,
		result => npc_irq
	);

	regir: pipeir port map(
		pc4 => pc4,
		ins => ins,
		wir => wpcir,
		clk => clock,
		clrn => resetn,
		cen => cen,
		irq => irqmaskf,
		irqmask => irqmask,
		pcf => pcf,
		inst => inst
	);
	inst_out <= inst;
	irqmask_out <= irqmask;
	idecode: pipeid port map(
		-- Input ports
		-- to control unit
		mwreg => mwreg,
		mm2reg => mm2reg,
		mwmem => mwmem,
		mdesr => mdesr,
		ewreg => ewreg,
		em2reg => em2reg,
		edesr => edesr,
		-- from pipeir
		pcf => pcf,
		inst => inst,
		irqmask => irqmask,
		-- from pipewreg
		wrfnd => wrfnd,
		-- from pipewb
		wrfdi => wrfdi,
		-- from pipeexe
		ealu => ealu,
		-- from pipemreg
		malu => malu,
		-- from pipemem
		mmo => mmo,
		dcacheok => dcacheok,
		-- from pipemwreg
		wwreg => wwreg,
		-- from outside
		clk => clock,
		clrn => resetn,		
		-- Output ports
		cen => cen,
		-- to pipeif
		fwda_out => fwda_out,
		fwdb_out => fwdb_out,
		bpc => bpc,
		branch => branch,
		jpatch => jpatch,
		iret => iret,		
		nostall => wpcir,
		-- to pipedereg
		wreg => dwreg,
		m2reg => dm2reg,
		wmem => dwmem,
		aluc => daluc,
		aluimm => daluimm,
		a => da,
		b => db,
		imm => dimm,
		desr => ddesr,
		shift => dshift
	);
	
	regde: pipedereg port map(
		-- Input ports
		-- from pipeid
		dwreg => dwreg,
		dm2reg => dm2reg,
		dwmem => dwmem,
		daluc => daluc,
		daluimm => daluimm,
		da => da,
		db => db,
		dimm => dimm,
		ddesr => ddesr,
		dshift => dshift,
		-- from outside
		cen => cen,
		clk => clock,
		clrn => resetn,
		
		-- Output ports		
		ewreg => ewreg,
		em2reg => em2reg,
		ewmem => ewmem,
		-- to pipeexe
		ealuc => ealuc,
		ealuimm => ealuimm,
		ea => ea,
		eb => eb,
		eimm => eimm,
		eshift => eshift,
		-- to pipeid and pipeemreg
		edesr => edesr
	);
	da_out <= da;
	db_out <= db;
	dimm_out <= dimm;
--	ddesr_out <= ddesr;
--	aluc_out <= daluc;
--	wrfnd_out <= wrfnd;
--	wrfdi_out <= wrfdi;
	
	exec: pipeexe port map(
		-- Input ports
		-- from pipedereg
		ealuc => ealuc,
		ealuimm => ealuimm,
		ea => ea,
		eb => eb,
		eimm => eimm,
		eshift => eshift,
		-- Output ports
		ealu => ealu
	);
	ealu_out <= ealu;
--	edesr_out <= edesr;
	
	regem: pipeemreg port map(
		-- Input ports
		-- from pipedereg
		ewreg => ewreg,
		em2reg => em2reg,
		ewmem => ewmem,
		eb => eb,
		edesr => edesr,
		-- from pipeexe
		ealu => ealu,
		-- from outside
		cen => cen,
		clk => clock,
		clrn => resetn,
		-- Output ports
		-- to pipeid and pipemwreg
		mwreg => mwreg,
		mm2reg => mm2reg,
		-- to pipemem
		mwmem => mwmem,
		malu => malu,
		mb => mb,
		mdesr => mdesr
	);	
--	malu_out <= malu;
	mb_out <= mb;
	
	imem: pipemem port map(
		-- Input ports
		re => mm2reg,
		we => mwmem,
		a => malu,
		di => mb,
		clk => rom_clock,--clock,
		memclk => ram_clock,
		-- Output ports
		-- mmo
		dcacheok => dcacheok,
		dataout => mmo
	);
	mmo_out <= mmo;
	cen_out <= cen;
	dcacheok_out <= dcacheok;
--	mdesr_out <= mdesr;
	
	regmw: pipemwreg port map(
		-- Input ports
		-- from pipeemreg
		mwreg => mwreg,
		mm2reg => mm2reg,
		malu => malu,
		mdesr => mdesr,
		-- from pipemem
		mmo => mmo,
		-- from outside
		cen => cen,
		clk => clock,
		clrn => resetn,
		-- Output ports
		-- to pipeid
		wwreg => wwreg,
		-- to pipewb
		wm2reg => wm2reg,
		wmo => wmo,
		walu => walu,
		-- to pipeid wrfnd
		wdesr => wrfnd
	);
	
	wbmux: lpm_mux32 port map(
		data0x => walu,
		data1x => wmo,
		sel => wm2reg,
		result => wrfdi
	);
--	walu_out <= walu;
--	wmo_out <= wmo;
end struct;

